#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

#include "video.h"
#include "netThread.h"

#define MASTER_WAIT                     (15)
#define DEFAULT_SERVER_PORT             8100

static struct  timeval start_time;


static int calc_delay(struct  timeval *cur, struct  timeval *last) {

    long frame_interval = 1000000 / g_frame_rate;
    long diff;

    if (last->tv_sec == 0 && last->tv_usec == 0) {
        memcpy(&start_time, cur, sizeof(struct  timeval));
        return 0;
    } else {
        diff = (cur->tv_sec - last->tv_sec)*1000000 + cur->tv_usec - last->tv_usec;
        diff = frame_interval - diff;
        if (diff < 0) {
            //printf("system slow:%d\n", diff);
            diff = 0;
        }
        return diff;
    }
}


static void main_slaver(char *fname) {

    int ret;

    ret = video_open(fname);
    if (ret != 0) {
        return;
    }

    net_slaver_thread();

    video_close();
}

static void main_master(char *fname) {

    int wait_num = 0;
    int ret;
    pthread_t net_thread_id;
    struct  timeval last_frame_time, cur_frame_time;
    int delay;

    last_frame_time.tv_sec = 0;
    last_frame_time.tv_usec = 0;

    ret = pthread_create(&net_thread_id, NULL, (void *) net_master_thread,
            NULL);
    if (ret != 0) {
        printf("Create net thread error!\n");
    }

    ret = video_open(fname);
    if (ret != 0) {
        return;
    }

    while (g_client_num < 2) {
        printf("waiting ... %d\n", g_client_num);
        sleep(1);
        wait_num++;
        if (wait_num >= MASTER_WAIT) {
            printf("not enough clients connected, exit!\n");
            break;
        }
    }

    if (wait_num < MASTER_WAIT) {
        do {
            gettimeofday(&cur_frame_time,0);
            delay = calc_delay(&cur_frame_time, &last_frame_time);
            usleep(delay);
            memcpy(&last_frame_time, &cur_frame_time, sizeof(struct timeval));

            g_frame_num++;
            ret = video_play_frame();
        } while (ret == 0);
    }

    long diff = (cur_frame_time.tv_sec - start_time.tv_sec)*1000000 +
            cur_frame_time.tv_usec - start_time.tv_usec;

    printf("Play Time: %d:%d, frames: %d\n", (int)(diff/1000000), (int)(diff/1000), g_frame_num);

    g_frame_num = -1;
    usleep(100 * 1000);

    video_close();
}

static void main_run_allinone(char *fname) {

    char file_name[256];

    strcpy(file_name, fname);
    strcpy(g_server_addr, "127.0.0.1");
    g_server_port = DEFAULT_SERVER_PORT;

    if (fork() == 0) {
        // child process
        strcat(file_name, "_b.mp4");
        main_slaver(file_name);
    } else {
        if (fork() == 0) {
            // child process
            strcat(file_name, "_c.mp4");
            main_slaver(file_name);
        } else {
            // father process
            strcat(file_name, "_a.mp4");
            main_master(file_name);
        }
    }

}

static void print_usage(char *cmd) {
    printf("Usage: %s video_file_prefix\n", cmd);
    printf("or: %s master server_port video_file_name\n", cmd);
    printf("or: %s slaver server_ip server_port video_file_name\n", cmd);
}

int main(int argc, char **argv) {

    if (argc != 2 && argc != 4 && argc != 5) {
        print_usage(argv[0]);
        exit(1);
    }

    if (argc == 2) {
        main_run_allinone(argv[1]);
    } else if (argc == 4) {
        if (strcmp(argv[1], "master") == 0) {
            g_server_port = atoi(argv[2]);
            main_master(argv[3]);
        } else {
            print_usage(argv[0]);
        }
    } else if (argc == 5) {
        if (strcmp(argv[1], "slaver") == 0) {
            strcpy(g_server_addr, argv[2]);
            g_server_port = atoi(argv[3]);
            main_slaver(argv[4]);
        } else {
            print_usage(argv[0]);
        }
    }

    exit(0);
}
